#pragma once

#include "ReduceAction.h"

#include "Behavior.h"
#include "InputPin.h"
#include "OutputPin.h"

namespace uml {

const bool ReduceAction::isOrdered_default_ = false;
ReduceAction::ReduceAction(const QString& umlType)
    : Action(umlType) {}

void ReduceAction::fromJson(const QJsonObject& json, QStringList& errorList) {
    if (json.isEmpty()) {
        return;
    }

    Action::fromJson(json, errorList);
    collection_ = JsonSerializable::create<InputPin>(json.value("collection"), errorList);

    isOrdered_ = json.value("isOrdered").toBool(isOrdered_default_);
    reducer_ = JsonSerializable::create<Behavior>(json.value("reducer"), errorList);

    result_ = JsonSerializable::create<OutputPin>(json.value("result"), errorList);

}

void ReduceAction::toJson(QJsonObject& json) {
    Action::toJson(json);
    if (collection_) {
        QJsonObject collection_json;
        collection_->toJson(collection_json);
        json.insert("collection", collection_json);
    }
    if (isOrdered_ != isOrdered_default_) {
        json.insert("isOrdered", isOrdered_);
    }
    if (reducer_) {
        QJsonObject reducer_json;
        reducer_->toJson(reducer_json);
        json.insert("reducer", reducer_json);
    }
    if (result_) {
        QJsonObject result_json;
        result_->toJson(result_json);
        json.insert("result", result_json);
    }
}

/// <summary>
/// collection getter
/// The InputPin that provides the collection to be reduced.
/// </summary>
shared_ptr<InputPin> ReduceAction::collection() const {
    return collection_;
}

/// <summary>
/// collection setter
/// The InputPin that provides the collection to be reduced.
/// </summary>
void ReduceAction::setCollection(shared_ptr<InputPin> value) {
    collection_ = value;
}

/// <summary>
/// isOrdered getter
/// Indicates whether the order of the input collection should determine the order
/// in which the reducer Behavior is applied to its elements.
/// </summary>
bool ReduceAction::isOrdered() const {
    return isOrdered_;
}

/// <summary>
/// isOrdered setter
/// Indicates whether the order of the input collection should determine the order
/// in which the reducer Behavior is applied to its elements.
/// </summary>
void ReduceAction::setIsOrdered(bool value) {
    isOrdered_ = value;
}

/// <summary>
/// reducer getter
/// A Behavior that is repreatedly applied to two elements of the input collection
/// to produce a value that is of the same type as elements of the collection.
/// </summary>
shared_ptr<Behavior> ReduceAction::reducer() const {
    return reducer_;
}

/// <summary>
/// reducer setter
/// A Behavior that is repreatedly applied to two elements of the input collection
/// to produce a value that is of the same type as elements of the collection.
/// </summary>
void ReduceAction::setReducer(shared_ptr<Behavior> value) {
    reducer_ = value;
}

/// <summary>
/// result getter
/// The output pin on which the result value is placed.
/// </summary>
shared_ptr<OutputPin> ReduceAction::result() const {
    return result_;
}

/// <summary>
/// result setter
/// The output pin on which the result value is placed.
/// </summary>
void ReduceAction::setResult(shared_ptr<OutputPin> value) {
    result_ = value;
}

} // namespace uml
